<template>
  <div class="department-container">
    <div class="app-container">
      <div class="company">
        <div class="c-left">{{ companyInfo.name }}</div>
        <div class="c-right">
          <div class="cr-left">负责人</div>
          <!-- 碰到一个复杂的页面结构，第一反应，一定是去找其他人写的组件，要么是element-ui，要么去百度 搜 vue 下拉插件 -->
          <div class="cr-right">
            <!-- 下面代码复制过来 -->
            <el-dropdown>
              <span class="el-dropdown-link">
                操作<i class="el-icon-arrow-down el-icon--right" />
              </span>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item @click.native="addDepartment('')">添加子部门</el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </div>
        </div>
      </div>
      <div class="tree">
        <el-tree :data="data" :props="defaultProps" @node-click="handleNodeClick">
          <!-- 下面这个结构，就是我们通过自定义的html 通过插槽传递给el-tree组件，让他替换el-tree里面默认的结构 -->
          <!-- <div slot-scope="{node, data}" class="company"> -->
          <!-- 作用域插槽的 aaa 是组件 el-tree 给我往外暴露的一个 属性， 是一个对象，里面有node属性和data属性 -->
          <div slot-scope="{data: mydata}" class="company">
            <div class="c-left" @click="testScope(mydata)">{{ mydata.name }}</div>
            <div class="c-right">
              <div class="cr-left">{{ mydata.manager }}</div>
              <!-- 碰到一个复杂的页面结构，第一反应，一定是去找其他人写的组件，要么是element-ui，要么去百度 搜 vue 下拉插件 -->
              <div class="cr-right">
                <!-- 下面代码复制过来 -->
                <el-dropdown>
                  <span class="el-dropdown-link">
                    操作<i class="el-icon-arrow-down el-icon--right" />
                  </span>
                  <el-dropdown-menu slot="dropdown">
                    <el-dropdown-item @click.native="addDepartment(mydata)">添加子部门</el-dropdown-item>
                    <el-dropdown-item @click.native="editDepartment(mydata)">编辑部门</el-dropdown-item>
                    <!-- mydata.children && mydata.children.length === 0 -->
                    <el-dropdown-item v-if="!mydata.children || mydata.children.length === 0" @click.native="deleteDepBtn(mydata)">删除部门</el-dropdown-item>
                  </el-dropdown-menu>
                </el-dropdown>
              </div>
            </div>
          </div>
        </el-tree>
      </div>
    </div>

    <!-- 弹框， 因为对话框是通过 document.body.appendChid(xxx) -->
    <!-- 弹框可以放任意位置，但为了和我们的业务代码，有区别，分隔开，一般放在同级 -->
    <!-- v-if="dialogVisible" -->
    <el-dialog
      v-if="dialogVisible"
      :title="isEdit ? '编辑部门' : '新增部门'"
      :visible.sync="dialogVisible"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :show-close="false"
    >
      <update-dialog ref="dialogRef" :arr-list-to-child="arrListToChild" :is-edit="isEdit" :current-pid="currentPid" @MyCloseEvent="dialogVisible = false" @success="updateSuccess" />
    </el-dialog>
  </div>
</template>

<script>
import { getDepartmentInfoReqest, deleteDeparmentByIdRequest } from '@/api/department'
import { transformListToTree } from '@/utils'
import UpdateDialog from './UpdateDialog.vue'

export default {
  components: {
    UpdateDialog
  },
  data() {
    return {
      data: [],
      defaultProps: {
        children: 'children',
        label: 'label'
      },
      companyInfo: {},
      dialogVisible: false,
      currentPid: '',
      // 当前的模态框是编辑还是新增
      isEdit: false,
      // 获取父组件里面所有的平铺数据，传递给子组件使用
      arrListToChild: []
    }
  },
  async created() {
    // 执行很多初始化的操作, created函数里面不要写代码代码，一般是在外面封装函数，在里面调用函数
    this.getDepartmentInfo()
  },
  methods: {
    async getDepartmentInfo() {
      // async await 就是把异步的代码，当初同步的形式来写
      // try {
      //   const res = await getDepartmentInfoReqest()
      //   console.log(res)
      // } catch (err) {
      //   console.log('获取组织信息接口失败：', err)
      // }
      // async是es8 2017年的语法， promise是es6 2015年的语法， 2015年之前是回调函数的写法
      getDepartmentInfoReqest().then(res => {
        // then有两个参数，都是函数，第一个函数是 请求成功后执行，第二个函数是请求失败后执行
        console.log('请求成：', res)
        // forEach filter map  reduce复杂 --- 函数的参数和函数的返回值
        // some every 数组循环次数 并不一定是数组的长度的次数
        // this.arrListToChild = res.data.depts.map(item => ({name: xxx}))
        this.arrListToChild = res.data.depts.map(item => {
          return {
            id: item.id,
            pid: item.pid,
            name: item.name,
            code: item.code
          }
        })
        this.companyInfo = res.data.depts.shift()
        // this.data = res.data.depts
        // this.data = transformListToTree(res.data.depts)
        this.data = transformListToTree(res.data.depts, '')
      }, err => {
        console.log('请求失败：', err)
      })
    },
    handleNodeClick(data) {
      console.log(data)
    },
    testScope(a, b) {
      console.log(a)
      console.log(b)
    },
    // 部门新增
    addDepartment(param) {
      // 自己和自己说变量的作用
      this.isEdit = false
      if (param) {
        this.currentPid = param.id
      } else {
        this.currentPid = ''
      }
      this.dialogVisible = true
    },
    // 部门编辑的方法
    editDepartment(param) {
      this.isEdit = true
      this.currentPid = param.id
      this.dialogVisible = true

      // 首先vue更新页面是异步的操作， 比如我们更改了5个数据，vue不会没更新一个数据，给我们渲染一下页面
      // 而是会把这些异步更新放到一些事件队列里面去，等同步更新完了以后，在去调用异步事件队列的方法，给我们
      // 一次性的更新dom结构， nextTick就是 给我们一个方法，等dom更新结束以后，在做一些操作
      // this.$nextTick(() => {
      //   // 等待我们的dialog组件创建成功了以后 （真实dom绑定到了页面上面，再去获取refs的元素）
      //   console.log(this.$refs.dialogRef)
      //   this.$refs.dialogRef.getDeparmentById()
      // })
    },
    updateSuccess() {
      // 创建成功以后，关闭弹窗，是由子组件触发的这个函数
      this.dialogVisible = false
      // 回到了父组件以后， 当前页面的数据还是旧的，不需要手动去刷新页面
      // 页面上的树形结构数据，是发请求获取的，我们只需在发一遍请求即可
      // SPA 单页面应用程序
      this.getDepartmentInfo()
      // 不需要 window.location.reload()  体验不好，页面会闪一下
    },
    // 学会一种将 异步请求代码封装到另外一个函数里面去
    async deleteDeparmentById(id) {
      await deleteDeparmentByIdRequest(id)
      // 只有删除成功或失败以后，才调用接口，获取新的tree的数据
      this.getDepartmentInfo()
    },
    deleteDepBtn(params) {
      this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        // 我们这里是点击了确定，就去调用删除的方法
        this.deleteDeparmentById(params.id)
        this.$message({
          type: 'success',
          message: '删除成功!'
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        })
      })
    }
  }
}
</script>

<style lang="scss">
/* // 写样式的时候，代码不要写散了，要用一个大类，包裹着里面所有的类
// 方便以后 代码进行谦虚 */
.app-container {
  .company {
    // 容器
    display: flex;
    width: 100%;
    .c-left {
      // 项目
      flex: 1 1 80%;
      padding: 5px 10px;
      // background-color: lightblue
    }
    .c-right {
      // 项目
      flex: 1 1 20%;
      padding: 5px 10px;
      // background-color: lightblue;
      // 把这个div项目， 又当做一个容器
      display: flex;
      .cr-left {
        flex: 1 1 50%;
        // background-color: lightsalmon
      }
      .cr-right {
        flex: 1 1 50%;
        // background-color: lightgreen
      }
    }
  }
}
</style>
